import React, {memo, useEffect, useState} from 'react';
import Header from "../../../components/main-header/Header";

import "./export.css";
import "./docTool.css";
import Title from "../../../components/Title/Title";
import {TREE_DATA, TREE_DATA_CN, updateReport, updateReportCn, translateGene} from "./config";
import {message, Tree, Upload} from "antd";
import {useDispatch, useSelector} from "react-redux";
import {saveExportObj, saveExportObjCn, saveReduxCheckedKeys, saveScaleIndex} from "./store/actionCreators";
import {calcMMSS, deepClone} from "../../../common/utils";
import {AMPLIFICATION} from "../protocol/config";
import {BASE_URL} from "../../../services/config";

export default memo(function Export() {
  const dispatch = useDispatch();
  const {endPointSetting, exportObj, exportObjCn, reduxCheckedKeys, scaleIndex, data, analysisShowLineArr, isCN, geneSetting, tableData, allelicTableData, failureReport, rfuResult} = useSelector(
    state => ({
      endPointSetting: state.endPointReducer.endPointSetting,
      exportObj: state.exportReducer.exportObj,
      exportObjCn: state.exportReducer.exportObjCn,
      reduxCheckedKeys: state.exportReducer.reduxCheckedKeys,
      scaleIndex: state.exportReducer.scaleIndex,
      data: state.dataReducer.data,
      analysisShowLineArr: state.plateReducer.analysisShowLineArr,  //  包含可以画线的well(同时有target和sampleName)
      isCN: state.languageReducer.isCN,
      geneSetting: state.geneSettingReducer.geneSetting,
      tableData: state.geneSettingReducer.tableData,
      allelicTableData: state.allelicReducer.allelicTableData,
      failureReport: state.quanlityControlReducer.failureReport,
      rfuResult: state.endPointReducer.rfuResult
    }));
  const [checkedKeys, setCheckedKeys] = useState(reduxCheckedKeys);
  const [showKeys, setShowKeys] = useState(reduxCheckedKeys);
  const [imageUrl, setImageUrl] = useState("");
  const [title, setTitle] = useState(exportObj.header.title);
  const [subTitle, setSubTitle] = useState(exportObj.header.subTitle);
  const [alignment, setAlignment] = useState("center");
  const [alignmentIndex, setAlignmentIndex] = useState(1);
  const alignmentArr = ["left", "center", "right"];

  useEffect(() => {
    let cloneExportObj = {};
    cloneExportObj = deepClone(isCN ? exportObjCn : exportObj, cloneExportObj);

    //  Experiment
    cloneExportObj.experiment.information = {
      name: data.experimentName,
      barcode: data.barcode,
      userName: data.userName,
      instrumentName: "",
      blockType: ""
    };
    cloneExportObj.experiment.parameterSetting = {
      reactionVolume: data.reactionVolume,
      lidHeatingSwitch: isCN ? "是" : "YES",
      coverTemp: data.coverTemp,
      lidCloseTemp: data.lidCloseTemp
    };
    let plateLayout = [
      ["", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
      ["A", "", "", "", "", "", "", "", "", "", "", "", ""],
      ["B", "", "", "", "", "", "", "", "", "", "", "", ""],
      ["C", "", "", "", "", "", "", "", "", "", "", "", ""],
      ["D", "", "", "", "", "", "", "", "", "", "", "", ""],
      ["E", "", "", "", "", "", "", "", "", "", "", "", ""],
      ["F", "", "", "", "", "", "", "", "", "", "", "", ""],
      ["G", "", "", "", "", "", "", "", "", "", "", "", ""],
      ["H", "", "", "", "", "", "", "", "", "", "", "", ""]
    ];

    //  Plate
    data.wells.forEach(item => {
      let targetsName = "";
      item.targets.forEach(it => targetsName = targetsName + it.name + ",");
      (item.sampleName || targetsName) && (plateLayout[item.row + 1][item.col + 1] = `${item.sampleName}\n${targetsName.slice(0, -1)}`);
    });
    cloneExportObj.plate.plateLayout = plateLayout;

    //  target
    let targets = [["Name", "Color", "Channel", "Quencher", "Comments"]];
    let targets_cn = [["名称", "颜色", "通道", "淬灭基团", "备注"]];
    let target = isCN ? targets_cn : targets;
    data.plateSetting.targets.forEach(item => target.push([item.name, item.color, item.channel, item.quencher, item.comments]));
    cloneExportObj.plate.target = target;

    //  sample
    let samples = [["Name", "Color", "Task", "Comments"]];
    let samples_cn = [["名称", "颜色", "类型", "备注"]];
    let sample = isCN ? samples_cn : samples;
    data.plateSetting.samples.forEach(item => sample.push([item.name, item.color, item.type, item.comments]));
    cloneExportObj.plate.sample = sample;

    //  standard
    let standard = data.plateSetting.standard;
    cloneExportObj.plate.standard = {
      assignment: standard.assignment,
      dilutionFactor: standard.dilutionFactor,
      factor: standard.factor,
      increasing_decreasing: isCN ? (standard.increasing ? "升序" : "降序") : (standard.increasing ? "increasing" : "decreasing"),
      replicates: standard.replicates,
      selectTarget: "",
      standardAmount: standard.standardAmount,
      standardNumber: standard.standardNumber,
      unit: standard.unit
    };

    //  protocol
    let protocol = "", protocolIndex = 1;
    data.protocol.stages.forEach(item => {
      item.steps.forEach(it => protocol = protocol + `${protocolIndex++}. ${it.temperature}℃ Hold ${calcMMSS(it.time)}\n`);
      item.state === AMPLIFICATION && (protocol = protocol + `${protocolIndex++}. Go to step${protocolIndex - 2} for ${item.cycle} cycles\n`);
    });
    cloneExportObj.protocol.protocol = protocol;

    //  quantification data
    let quantificationData = [["Well", "Target", "Task", "Sample", "Cq", "Mean Cq", "Cq SD", "SQ"]];
    analysisShowLineArr.forEach(
      item => quantificationData.push([item.well.value, item.target.value, item.task.value, item.sample.value, item.cq.value, item.cqMean.value, item.cqSd.value, item.quantitySd.value]));
    cloneExportObj.analysis.quantificationData = quantificationData;

    //  melt data
    let meltData = [["Well", "Target", "Task", "Sample", "Melt Temp"]];
    analysisShowLineArr.forEach(
      item => meltData.push([item.well.value, item.target.value, item.task.value, item.sample.value, "TM1"]));
    cloneExportObj.analysis.meltData = meltData;

    //GeneExpression
    let modeArr = [];
    let mode, plotType, graphType, orientation, modes = "", geneSettingIndex = 1;
    mode = isCN ? translateGene(geneSetting.mode) : geneSetting.mode;
    plotType = isCN ? translateGene(geneSetting.plotType) : geneSetting.plotType;
    graphType = isCN ? translateGene(geneSetting.graphType) : geneSetting.graphType;
    orientation = isCN ? translateGene(geneSetting.orientation) : geneSetting.orientation;
    modeArr.push(mode, plotType, graphType, orientation);
    isCN ? modeArr.forEach((item, index) => {
        index === 0 && (modes = modes + `${geneSettingIndex++}.分析模式:${mode}\n`);
        index === 1 && (modes = modes + `${geneSettingIndex++}.绘图类型: ${plotType}\n`);
        index === 2 && (modes = modes + `${geneSettingIndex++}.图谱类型:${graphType}\n`);
        index === 3 && (modes = modes + `${geneSettingIndex++}.方向:${orientation}\n`);
      }) :
      modeArr.forEach((item, index) => {
        index === 0 && (modes = modes + `${geneSettingIndex++}.Model:${mode}\n`);
        index === 1 && (modes = modes + `${geneSettingIndex++}.PlotType: ${plotType}\n`);
        index === 2 && (modes = modes + `${geneSettingIndex++}.GraphType:${graphType}\n`);
        index === 3 && (modes = modes + `${geneSettingIndex++}.Orientation:${orientation}\n`);
      });
    //返回一段字符串，进行截取成数组输出mode的设置参数
    cloneExportObj.analysis.geneExpressionMode = modes;

    //GeneExpression Data
    let geneExpressionData = [["Sample", "Target", "Cq Mean", "ΔCq Mean", "ΔCq SD", "ΔΔCq", "RQ", "RQ Min","RQ Max"]];
    let geneExpressionData_Relative = [["Sample", "Target", "Cq Mean", "Quantity Mean", "Quantity Sd", "RQ", "RQ Min", "RQ Max"]];
    tableData.forEach(
      item => {
        if (geneSetting.mode === "Relative Standard Curve" || "相对标准曲线") {
          geneExpressionData_Relative.push(
            [item.biological.value, item.target.value, item.cqMean.value.toFixed(3), item._cqMean.value.toFixed(3), item._cqSd.value.toFixed(3), item.rq.value.toFixed(3),
              item.rqMin.value.toFixed(3), item.rqMax.value.toFixed(3)]);
        } else {
          geneExpressionData.push(
            [item.biological.value, item.target.value, item.cqMean.value.toFixed(3), item._cqMean.value.toFixed(3), item._cqSd.value.toFixed(3), item.__cq.value.toFixed(3), item.rq.value.toFixed(3),
              item.rqMin.value.toFixed(3),item.rqMax.value.toFixed(3)]);
        }
      }
    );
    if (geneSetting.mode === "Relative Standard Curve" || "相对标准曲线") {
      cloneExportObj.analysis.geneExpressionData = geneExpressionData_Relative;
    } else {
      cloneExportObj.analysis.geneExpressionData = geneExpressionData;
    }
    //Allelic
    let allelicData = [["Well", "Task", "Allele1 Cq", "Allele2 Cq", "Allele1 RFU", "Allele2 RFU", "Call", "Comments"]];
    let allelicDataCn = [["反应孔", "类型", "等位基因1 Cq", "等位基因2 Cq", "等位基因1 RFU", "等位基因2 RFU", "结果", "描述"]];
    allelicData = isCN ? allelicDataCn : allelicData;
    allelicTableData.forEach(item => {
      allelicData.push([item.well, item.task, item.allele1Cq, item.allele2Cq, item.allele1RFU, item.allele2RFU, item.call, item.comments]);
    });
    cloneExportObj.analysis.allelicData = allelicData;

    //Quanlity control
    let controlData = [["Well", "NEG", "NTC", "POS", "STD", "EFF", "R2", "RDEV"]];
    failureReport.forEach(item => {
      item.ntc = item.ntc ? "fail" : "";
      item.neg = item.neg ? "fail" : "";
      item.pos = item.pos ? "fail" : "";
      item.std = item.std ? "fail" : "";
      item.eff = item.eff ? "fail" : "";
      item.r2 = item.r2 ? "fail" : "";
      item.rdev = item.rdev ? "fail" : "";
      controlData.push([item.well, item.neg, item.ntc, item.pos, item.std, item.eff, item.r2, item.rdev]);
    });
    cloneExportObj.analysis.failureReportData = controlData;

    //End-Point Setting
    let endPointSettingData = [["Target", "Channel", "Ave Cycles", "RFU%", "RFU Lowest", "RFU Highest", "NTC Ave", "Cut - off"]];
    let endPointSettingDataCn = [["基因", "通道", "循环数", "RFU%", "RFU最低值", "RFU最高值", "NTC RFU平均值 ", "界限值"]];
    endPointSettingData = isCN ? endPointSettingDataCn : endPointSettingData;
    endPointSetting.forEach(item => {
      endPointSettingData.push([item.target, item.channel, item.cycleStatus, item.rfu, item.rfuLowest.toFixed(3),
        item.rfuLowest.toFixed(3), item.ntcAve ? Number(item.ntcAve).toFixed(3) : "", item.cutOff ? Number(item.cutOff).toFixed(3) : ""]);
    });
    cloneExportObj.analysis.endPointSettingData = endPointSettingData;

    //RFU Result
    let rfuResultData = [["Well", "Target", "Task", "Sample", "End RFU", "Call"]];
    let rfuResultDataCn = [["反应孔", "基因", "类型", "样品", "终点荧光值", "结果"]];
    rfuResultData = isCN ? rfuResultDataCn : rfuResultData;
    rfuResult.forEach(item => {
      if (item.show) {
        if (typeof item.call !== "string") {
          if (item.call) {
            item.call = "Positive (+)";
          } else {
            item.call = "Negative (-)";
          }
        } else {
          item.call = "";
        }
        rfuResultData.push([item.well, item.target, item.task, item.sample, Number(item.endRfu).toFixed(3), item.call]);
      }
    });


    cloneExportObj.analysis.endPointData = rfuResultData;

    //  TODO:
    //  设置显示的内容
    let cloneShowKeys = [...showKeys];
    cloneShowKeys = cloneShowKeys.map(item => item.split("-")[1]);
    getShowItem(cloneExportObj, cloneShowKeys);
    isCN ? updateReportCn(cloneExportObj)
      : updateReport(cloneExportObj);
    isCN ? dispatch(saveExportObjCn(cloneExportObj))
      : dispatch(saveExportObj(cloneExportObj));
  }, [scaleIndex, showKeys, data]);

  //  设置exportObj显示的内容
  function getShowItem(obj, treeKeys) {
    let keys = Object.keys(obj);
    keys.forEach(item => {
      if (typeof obj[item] === "boolean") {
        if (!treeKeys.includes(item)) {
          obj[item] = false;
        } else {
          obj[item] = true;
          treeKeys.splice(treeKeys.indexOf(item), 1);
        }
      } else if (typeof obj[item] === "object" && obj[item] !== null) {
        getShowItem(obj[item], treeKeys);
      }
    });
  }

  //  选择树
  function onCheck(checkedKeysValue, e) {
    const showKeys = checkedKeysValue.concat(e.halfCheckedKeys);
    setCheckedKeys(checkedKeysValue);
    dispatch(saveReduxCheckedKeys(checkedKeysValue));
    setShowKeys(showKeys);
  }

  //  缩放
  function scaleAction(type) {
    dispatch(saveScaleIndex(8));
    if (type === "up") {
      scaleIndex >= 10
        ? dispatch(saveScaleIndex(10))
        : dispatch(saveScaleIndex(scaleIndex + 1));
    } else {
      scaleIndex <= 0
        ? dispatch(saveScaleIndex(0))
        : dispatch(saveScaleIndex(scaleIndex - 1));
    }
  }

  //  获取头像Base64
  function getBase64(img, callback) {
    const reader = new FileReader();
    reader.addEventListener('load', () => callback(reader.result));
    reader.readAsDataURL(img);
  }

  //  上传之前的钩子
  function beforeUpload(file) {
    const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
    if (!isJpgOrPng) {
      message.error('Please upload JPG/PNG files');
    }
    const isLt2M = file.size / 1024 / 1024 < 2;
    if (!isLt2M) {
      message.error('The image is too large, no more than 2MB');
    }
    return isJpgOrPng && isLt2M;
  }

  //  上传文件改变时的状态
  function handleChange(info) {
    if (info.file.status === 'uploading') {
      return;
    }
    if (info.file.status === 'done') {
      getBase64(info.file.originFileObj, imageUrl => setImageUrl(imageUrl));
    }
  }

  //  header设置
  function applyAction() {
    let cloneExportObj = {};
    cloneExportObj = deepClone(isCN ? exportObjCn : exportObj, cloneExportObj);
    cloneExportObj.header.title = title;
    cloneExportObj.header.subTitle = subTitle;
    cloneExportObj.header.imgLogo = imageUrl.split(',')[1];
    cloneExportObj.header.headerAlign = alignment;
    isCN ? updateReportCn(cloneExportObj)
      : updateReport(cloneExportObj);
    isCN ? dispatch(saveExportObjCn(cloneExportObj))
      : dispatch(saveExportObj(cloneExportObj));
  }

  //  选择alignment
  function selectAlignment(value, indey) {
    setAlignmentIndex(indey);
    setAlignment(value);
  }

  return (
    <div>
      <Header name={isCN ? "报告导出" : "Report"}
              imgPosition="-250px"
              isSave={true}
              isSaveWordAndPdf={true}
      />
      <section className="mainSection exportPage">
        <div>
          <section className="exportPageLeftTitle">
            <div>{isCN ? "报告预览" : "Report Preview"}</div>
            <ul>
              <li onClick={() => scaleAction("down")}>-</li>
              <li onClick={() => scaleAction("up")}>+</li>
            </ul>
          </section>
          <section id="container"
                   style={{height: "calc(100% - 50px)"}}
                   className={`exportPageLeftBox scrollBarStyle scale${scaleIndex}`}
          />
        </div>
        <div>
          <section className="exportPageRightSelectTree">
            <Title name={isCN ? "导出选择" : "Export Select"}/>
            <div>
              <Tree
                checkable
                onCheck={onCheck}
                checkedKeys={checkedKeys}
                treeData={isCN ? TREE_DATA_CN : TREE_DATA}
              />
            </div>
            <div></div>
          </section>
          <section className="exportPageRightMenu">
            <Title name={isCN ? "报告标题" : "Report Header"} btn="Apply" btnAction={applyAction}/>
            <div>
              <div>{isCN ? "标题" : "Title"}</div>
              <input type="text"
                     value={title}
                     onChange={e => setTitle(e.target.value)}
              />
            </div>
            <div>
              <div>{isCN ? "副标题" : "Sub-Title"}</div>
              <input type="text"
                     value={subTitle}
                     onChange={e => setSubTitle(e.target.value)}
              />
            </div>
            <div>
              <div>
                <div>Logo</div>
                <Upload username="avatar"
                        listType="picture-card"
                        className="avatar-uploader"
                        showUploadList={false}
                        beforeUpload={beforeUpload}
                        onChange={handleChange}
                        action={`${BASE_URL}/uploadAction/upload`}
                >
                  {imageUrl ? <img src={imageUrl} alt="avatar" style={{width: 190, height: 90}}/> : <div>Select</div>}
                </Upload>
              </div>
              <div className="reportHeaderAlignment">
                <div>{isCN ? "对齐方式" : "Alignment"}</div>
                {
                  alignmentArr.map((item, index) => (
                    <div key={item}
                         style={{borderStyle: index === alignmentIndex ? "dashed" : "solid"}}
                         onClick={() => selectAlignment(item, index)}
                    />
                  ))
                }
              </div>
            </div>
          </section>
        </div>
      </section>
    </div>
  );
});